package com.wholeintech.wirednet;

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.wholeintech.knx.KNXDataProcess;
import com.wholeintech.dao.DeviceDao;
import com.wholeintech.utils.DevType;
import com.wholeintech.zigbee.gw.DeviceManager;
import com.wholeintech.utils.CommonUtil;
import com.wholeintech.entity.DeviceDb;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import static com.wholeintech.utils.CommonIntent.ACTION_DEV_DEVCHANAGE;

/**
 * 有线网设备控制类
 */
public class WrdNetDeviceControl {

    private final static String TAG = "WireNetService-Control";
    private final static int WIRDNET_RESPONSE = 1;

    static WrdNetDeviceControl mDeviceControl;
    private final Handler responseHandler;

    public Context mContext;    //Add by hy,2017/06/21

    Queue<JSONObject> netSendDataQueue = new LinkedList<JSONObject>();        //Add by hy,2018/03/27

    public WrdNetDeviceControl(Handler handler, Context context) {
        this.responseHandler = handler;
        this.mContext = context;    //Add by hy,2017/06/21
    }

    public static WrdNetDeviceControl getInstance(Handler handler, Context context) {
        if (mDeviceControl == null) {
            mDeviceControl = new WrdNetDeviceControl(handler, context);
        }
        return mDeviceControl;
    }

    public void wireNetPacketAndControl(final Intent intent, final DeviceDb me, final DeviceDb gwDev, final String device_ip) {
        KNXDataProcess mKnxDevice = new KNXDataProcess(mContext);  //Add by hy,2017/06/21
        JSONObject object = new JSONObject();
        ArrayList<String> KnxStr;
        if (me.getNetType() == DeviceManager.KNX_NETWORK) {
            KnxStr = mKnxDevice.getPackStr(me.getDevId(), intent);

            for (int i = 0; i < KnxStr.size(); i++) {
                deviceControlPacket(me, device_ip, object, KnxStr.get(i));//生成指定格式的指令
                sendDeviceControlCmd(object, intent, me, device_ip);//发送指定到ip/zigbee设备
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } else {
            deviceControlPacket(me, gwDev, device_ip, object);        //生成指定格式的指令
            sendDeviceControlCmd(object, intent, me, device_ip);      //发送指定到ip/zigbee设备
        }
    }

    /**
     * 发送IP/Zigbee设备控制指令
     * @param object
     * @param intent
     * @param deviceDb
     * @param device_ip
     */
    public void sendDeviceControlCmd(final JSONObject object, final Intent intent, final DeviceDb deviceDb, final String device_ip) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL("http://" + device_ip + "/");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);

                    connection.setRequestMethod("POST");
                    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                    //往IP/Zigbee设备发送指令
                    //指令格式如：
                    //{"ip":"192.168.1.60","cmd":"control","packet":0,"type":1033,"deviceId":"103300800060","mac":"ED7A471B004B1200","sw":255,"brightness":0,"channel":255,"light8flag":128}
                    out.writeBytes(object.toString());

                    InputStream in;
                    int response_code = connection.getResponseCode();
                    if ((response_code != HttpURLConnection.HTTP_OK) &&
                            (response_code != HttpURLConnection.HTTP_CREATED) &&
                            (response_code != HttpURLConnection.HTTP_ACCEPTED)) {
                        in = connection.getErrorStream();
                    } else {
                        //判断是否是一拖8设备
                        if(deviceDb.getType() == DevType.DEV_TYPE_1_to_8){
                            //发送状态改变广播到上层
                            //查询所有子设备
                            ArrayList<String> subDevList = getSubDevList(deviceDb.getDevId());
                            if(subDevList!=null && subDevList.size()>0) {
                                //发送状态广播给上层
                                CommonUtil.sendBroadcastMsg(mContext, ACTION_DEV_DEVCHANAGE, deviceDb.getBoxId(), deviceDb.getDevId(), deviceDb.getType(), true, subDevList);
                                Log.e(TAG,"sendBroadcastMsg===5");
                            }
                        }
                        in = connection.getInputStream();
                    }

                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));

                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }

                    if (intent != null)
                        deviceControlResponseParse(intent, device_ip, response.toString());

                } catch (Exception e) {
                    e.printStackTrace();

                    if (intent != null)
                        deviceControlResponseParse(intent, device_ip, null);
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private ArrayList<String> getSubDevList(String strGwDevId){
        List<DeviceDb> subDevices = DeviceDao.getInstance().getSubDevices(strGwDevId);
        ArrayList<String> subDevList = new ArrayList<>();
        for(DeviceDb deviceDb1:subDevices){
            subDevList.add(deviceDb1.getDevId());
        }

        return subDevList;
    }

    private void deviceControlPacket(final DeviceDb me, final DeviceDb gwDev, final String device_ip, JSONObject object) {
        try {
            int device_type = Integer.parseInt(me.getDevId().substring(0, 4));
            object.put("ip", device_ip);
            object.put("cmd", "control");
            object.put("packet", 0);
            object.put("type", device_type);    //设备类型

            if (me.getGwDevId() != null || (gwDev.getGwDevId() != null)) { {
                    object.put("deviceId", me.getDevId());
                    if ((me.getGwDevId().length()>4) && me.getGwDevId().substring(0, 4).equals("2010")
                            || ((gwDev.getGwDevId().length()>4) && gwDev.getGwDevId().substring(0, 4).equals("2010"))) {        //Add by hy,2017/08/03
                        byte[] mac_byte = CommonUtil.exchangebyte(CommonUtil.hex2byte(me.getMacAddr()));    //Add by hy,2018/03/12
                        object.put("mac", CommonUtil.bytesToHexString(mac_byte, 0, mac_byte.length));
                    }
                }
            }

            switch (device_type) {
                case 1030:    //Add by hy,2017/08/04
                case 1031:
                    object.put("sw", me.getSw());
                    object.put("brightness", me.getBrightness());
                    object.put("color", me.getColor());
                    break;
                case 1033:
                    object.put("sw", me.getSw());
                    object.put("brightness", me.getBrightness());
                    object.put("channel", me.getColor()&0xff);
                    object.put("light8flag", (me.getColor()>>8)&0xff);
                    break;
                case 1050:
                case 2011:
                    object.put("sw", me.getSw());
                    object.put("mode", me.getMode());
                    object.put("temperature", me.getSetTemp());
                    object.put("wind", me.getWind());
                    break;
                case 1060:
                    object.put("sw", me.getSw());
                    object.put("mode", me.getMode());
                    object.put("temperature", me.getSetTemp());
                    break;
                case 1070:
                    object.put("sw", me.getSw());
                    object.put("wind", me.getWind());
                    object.put("mode", me.getMode());            //Add by hy,2017/07/19
                    object.put("sw2", me.getCurtainState());    //
                    break;
                //Add by hy,2017/08/04
                case 1040:
                    object.put("runstate", me.getCurtainState());
                    object.put("runstate2", me.getCurtainState2());
                    break;
                default:
                    break;
            }

            Log.d(TAG, "Json:" + object.toString());
        } catch (JSONException e) {
            // TODO Auto-generated catch block 聽
            e.printStackTrace();
        }
    }

    //Add by hy,2017/06/20
    private void deviceControlPacket(final DeviceDb me, final String device_ip, JSONObject object, String data) {
        try {
            int device_type = Integer.parseInt(me.getDevId().substring(0, 4));

            object.put("ip", device_ip);
            object.put("cmd", "trans_data");
            object.put("packet", 0);
            object.put("type", device_type);    //

            if (me.getGwDevId() != null) {
                object.put("deviceId", me.getDevId());
                if (me.getGwDevId().startsWith("2010")) {        //Add by hy,2017/08/03
                    byte[] mac_byte = CommonUtil.exchangebyte(CommonUtil.hex2byte(me.getMacAddr()));    //Add by hy,2018/03/12
                    object.put("mac", CommonUtil.bytesToHexString(mac_byte, 0, mac_byte.length));
                }
            }

            object.put("data", data);
            Log.d(TAG, "Json:" + object.toString());
        } catch (JSONException e) {
            // TODO Auto-generated catch block 聽
            e.printStackTrace();
        }
    }

    private void deviceControlResponseParse(Intent intent, String device_ip, String response) {
        Message message = new Message();
        message.what = WIRDNET_RESPONSE;
        message.obj = intent;

        if (response != null) {
            try {
                Log.d(TAG, response);
                JSONObject jsonObject = new JSONObject(response);

                if ((jsonObject.getString("ip").equals(device_ip)) &&
                        (jsonObject.getInt("packet") == 128)) {
                    message.arg1 = 0;
                } else {
                    message.arg1 = 1;
                }
            } catch (Exception e) {
                e.printStackTrace();
                message.arg1 = 1;
            } finally {

            }
        } else {
            message.arg1 = 1;
        }

        responseHandler.sendMessage(message);
    }

    /************* Add by hy,2018/03/27 **************/
    public void netSendBufferCread(final String device_ip, String cmd, String mac1, String bindDevId,
                                   String deviceId, String key) {
        JSONObject object = new JSONObject();

        try {
            int device_type = 0;

            if (deviceId != null)
                device_type = Integer.parseInt(deviceId.substring(0, 4));

            object.put("ip", device_ip);
            object.put("cmd", cmd);
            object.put("packet", 0);
            object.put("type", device_type);    //

            if (deviceId != null) {
                object.put("deviceId", new StringBuffer(deviceId).reverse().toString());
            }

            if (mac1 != null) {
                byte[] mac_byte = CommonUtil.exchangebyte(CommonUtil.hex2byte(mac1));    //Add by hy,2018/03/12
                object.put("mac", CommonUtil.bytesToHexString(mac_byte, 0, mac_byte.length));
            }
            if (bindDevId != null) {
                if(bindDevId.length() == 12)
                    object.put("bindDevId", new StringBuffer(bindDevId).reverse().toString());
                else
                    object.put("bindDevId", bindDevId);
            }

            if ((key != null) && (cmd.equals("set_key"))) {
                object.put("key", key);

            } else if ((key != null) && (cmd.equals("bind"))) {
                String[] param = key.split("and");
                object.put("group", Integer.parseInt(param[0]));
                object.put("config", Integer.parseInt(param[1]));
            }

        } catch (JSONException e) {
            // TODO Auto-generated catch block 聽
            e.printStackTrace();
        }

        if (netSendDataQueue != null) {
            netSendDataQueue.offer(object);
        }
    }

    public void netSendHandle() {
        JSONObject txObject;
        while ((txObject = netSendDataQueue.poll()) != null) {
            HttpURLConnection connection = null;
            try {
                Thread.currentThread().sleep(2000);//ms
            } catch (Exception e) {
                Log.d(TAG, "Thread sleep erro!");
            }
            Log.d(TAG, "netSendHandle run! ");
            try {
                URL url = new URL("http://" + txObject.getString("ip") + "/");//("https://www.baidu.com/");
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(8000);
                connection.setReadTimeout(8000);

                connection.setRequestMethod("POST");
                DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                out.writeBytes(txObject.toString());

                Log.d(TAG, "Send Json:" + txObject.toString());

                InputStream in;
                int response_code = connection.getResponseCode();
                if ((response_code != HttpURLConnection.HTTP_OK) &&
                        (response_code != HttpURLConnection.HTTP_CREATED) &&
                        (response_code != HttpURLConnection.HTTP_ACCEPTED)) {
                    in = connection.getErrorStream();
                } else {
                    in = connection.getInputStream();
                }

                BufferedReader reader = new BufferedReader(new InputStreamReader(in));

                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }

                Log.d(TAG, "response: " + response.toString());

            } catch (Exception e) {
                e.printStackTrace();

            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        }
    }
}
